'\"
'\" Copyright (c) 2003 Donal K. Fellows
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
.TH Tcl_DictObj 3 8.5 Tcl "Tcl Library Procedures"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
Tcl_NewDictObj, Tcl_DictObjPut, Tcl_DictObjGet, Tcl_DictObjRemove, Tcl_DictObjSize, Tcl_DictObjFirst, Tcl_DictObjNext, Tcl_DictObjDone, Tcl_DictObjPutKeyList, Tcl_DictObjRemoveKeyList \- manipulate Tcl values as dictionaries
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
Tcl_Obj *
\fBTcl_NewDictObj\fR()
.sp
int
\fBTcl_DictObjGet\fR(\fIinterp, dictPtr, keyPtr, valuePtrPtr\fR)
.sp
int
\fBTcl_DictObjPut\fR(\fIinterp, dictPtr, keyPtr, valuePtr\fR)
.sp
int
\fBTcl_DictObjRemove\fR(\fIinterp, dictPtr, keyPtr\fR)
.sp
int
\fBTcl_DictObjSize\fR(\fIinterp, dictPtr, sizePtr\fR)
.sp
int
\fBTcl_DictObjFirst\fR(\fIinterp, dictPtr, searchPtr,
                 keyPtrPtr, valuePtrPtr, donePtr\fR)
.sp
void
\fBTcl_DictObjNext\fR(\fIsearchPtr, keyPtrPtr, valuePtrPtr, donePtr\fR)
.sp
void
\fBTcl_DictObjDone\fR(\fIsearchPtr\fR)
.sp
int
\fBTcl_DictObjPutKeyList\fR(\fIinterp, dictPtr, keyc, keyv, valuePtr\fR)
.sp
int
\fBTcl_DictObjRemoveKeyList\fR(\fIinterp, dictPtr, keyc, keyv\fR)
.SH ARGUMENTS
.AS Tcl_DictSearch "**valuePtrPtr" in/out
.AP Tcl_Interp *interp in
If an error occurs while converting a value to be a dictionary value,
an error message is left in the interpreter's result value
unless \fIinterp\fR is NULL.
.AP Tcl_Obj *dictPtr in/out
Points to the dictionary value to be manipulated.
If \fIdictPtr\fR does not already point to a dictionary value,
an attempt will be made to convert it to one.
.AP Tcl_Obj *keyPtr in
Points to the key for the key/value pair being manipulated within the
dictionary value.
.AP Tcl_Obj **keyPtrPtr out
Points to a variable that will have the key from a key/value pair
placed within it.  May be NULL to indicate that the caller is not
interested in the key.
.AP Tcl_Obj *valuePtr in
Points to the value for the key/value pair being manipulated within the
dictionary value (or sub-value, in the case of
\fBTcl_DictObjPutKeyList\fR.)
.AP Tcl_Obj **valuePtrPtr out
Points to a variable that will have the value from a key/value pair
placed within it.  For \fBTcl_DictObjFirst\fR and
\fBTcl_DictObjNext\fR, this may be NULL to indicate that the caller is
not interested in the value.
.AP int *sizePtr out
Points to a variable that will have the number of key/value pairs
contained within the dictionary placed within it.
.AP Tcl_DictSearch *searchPtr in/out
Pointer to record to use to keep track of progress in enumerating all
key/value pairs in a dictionary.  The contents of the record will be
initialized by the call to \fBTcl_DictObjFirst\fR.  If the enumerating
is to be terminated before all values in the dictionary have been
returned, the search record \fImust\fR be passed to
\fBTcl_DictObjDone\fR to enable the internal locks to be released.
.AP int *donePtr out
Points to a variable that will have a non-zero value written into it
when the enumeration of the key/value pairs in a dictionary has
completed, and a zero otherwise.
.AP int keyc in
Indicates the number of keys that will be supplied in the \fIkeyv\fR
array.
.AP "Tcl_Obj *const" *keyv in
Array of \fIkeyc\fR pointers to values that
\fBTcl_DictObjPutKeyList\fR and \fBTcl_DictObjRemoveKeyList\fR will
use to locate the key/value pair to manipulate within the
sub-dictionaries of the main dictionary value passed to them.
.BE

.SH DESCRIPTION
.PP
Tcl dictionary values have an internal representation that supports
efficient mapping from keys to values and which guarantees that the
particular ordering of keys within the dictionary remains the same
modulo any keys being deleted (which removes them from the order) or
added (which adds them to the end of the order). If reinterpreted as a
list, the values at the even-valued indices in the list will be the
keys of the dictionary, and each will be followed (in the odd-valued
index) by the value associated with that key.
.PP
The procedures described in this man page are used to
create, modify, index, and iterate over dictionary values from C code.
.PP
\fBTcl_NewDictObj\fR creates a new, empty dictionary value.  The
string representation of the value will be invalid, and the reference
count of the value will be zero.
.PP
\fBTcl_DictObjGet\fR looks up the given key within the given
dictionary and writes a pointer to the value associated with that key
into the variable pointed to by \fIvaluePtrPtr\fR, or a NULL if the
key has no mapping within the dictionary.  The result of this
procedure is \fBTCL_OK\fR, or \fBTCL_ERROR\fR if the \fIdictPtr\fR cannot be
converted to a dictionary.
.PP
\fBTcl_DictObjPut\fR updates the given dictionary so that the given
key maps to the given value; any key may exist at most once in any
particular dictionary.  The dictionary must not be shared, but the key
and value may be.  This procedure may increase the reference count of
both key and value if it proves necessary to store them.  Neither key
nor value should be NULL.  The result of this procedure is \fBTCL_OK\fR, or
\fBTCL_ERROR\fR if the \fIdictPtr\fR cannot be converted to a dictionary.
.PP
\fBTcl_DictObjRemove\fR updates the given dictionary so that the given
key has no mapping to any value.  The dictionary must not be shared,
but the key may be.  The key actually stored in the dictionary will
have its reference count decremented if it was present.  It is not an
error if the key did not previously exist.  The result of this
procedure is \fBTCL_OK\fR, or \fBTCL_ERROR\fR if the \fIdictPtr\fR cannot be
converted to a dictionary.
.PP
\fBTcl_DictObjSize\fR updates the given variable with the number of
key/value pairs currently in the given dictionary. The result of this
procedure is \fBTCL_OK\fR, or \fBTCL_ERROR\fR if the \fIdictPtr\fR cannot be
converted to a dictionary.
.PP
\fBTcl_DictObjFirst\fR commences an iteration across all the key/value
pairs in the given dictionary, placing the key and value in the
variables pointed to by the \fIkeyPtrPtr\fR and \fIvaluePtrPtr\fR
arguments (which may be NULL to indicate that the caller is
uninterested in they key or variable respectively.)  The next
key/value pair in the dictionary may be retrieved with
\fBTcl_DictObjNext\fR.  Concurrent updates of the dictionary's
internal representation will not modify the iteration processing
unless the dictionary is unshared, when this will trigger premature
termination of the iteration instead (which Tcl scripts cannot trigger
via the \fBdict\fR command.)  The \fIsearchPtr\fR argument points to a
piece of context that is used to identify which particular iteration
is being performed, and is initialized by the call to
\fBTcl_DictObjFirst\fR.  The \fIdonePtr\fR argument points to a
variable that is updated to be zero of there are further key/value
pairs to be iterated over, or non-zero if the iteration is complete.
The order of iteration is implementation-defined.  If the
\fIdictPtr\fR argument cannot be converted to a dictionary,
\fBTcl_DictObjFirst\fR returns \fBTCL_ERROR\fR and the iteration is not
commenced, and otherwise it returns \fBTCL_OK\fR.
.PP
When \fBTcl_DictObjFirst\fR is called upon a dictionary, a lock is placed on
the dictionary to enable that dictionary to be iterated over safely without
regard for whether the dictionary is modified during the iteration. Because of
this, once the iteration over a dictionary's keys has finished (whether
because all values have been iterated over as indicated by the variable
indicated by the \fIdonePtr\fR argument being set to one, or because no
further values are required) the \fBTcl_DictObjDone\fR function must be called
with the same \fIsearchPtr\fR as was passed to \fBTcl_DictObjFirst\fR so that
the internal locks can be released. Once a particular \fIsearchPtr\fR is
passed to \fBTcl_DictObjDone\fR, passing it to \fBTcl_DictObjNext\fR (without
first initializing it with \fBTcl_DictObjFirst\fR) will result in no values
being produced and the variable pointed to by \fIdonePtr\fR being set to one.
It is safe to call \fBTcl_DictObjDone\fR multiple times on the same
\fIsearchPtr\fR for each call to \fBTcl_DictObjFirst\fR.
.PP
The procedures \fBTcl_DictObjPutKeyList\fR and
\fBTcl_DictObjRemoveKeyList\fR are the close analogues of
\fBTcl_DictObjPut\fR and \fBTcl_DictObjRemove\fR respectively, except
that instead of working with a single dictionary, they are designed to
operate on a nested tree of dictionaries, with inner dictionaries
stored as values inside outer dictionaries.  The \fIkeyc\fR and
\fIkeyv\fR arguments specify a list of keys (with outermost keys
first) that acts as a path to the key/value pair to be affected.  Note
that there is no corresponding operation for reading a value for a
path as this is easy to construct from repeated use of
\fBTcl_DictObjGet\fR. With \fBTcl_DictObjPutKeyList\fR, nested
dictionaries are created for non-terminal keys where they do not
already exist. With \fBTcl_DictObjRemoveKeyList\fR, all non-terminal
keys must exist and have dictionaries as their values.
.SH EXAMPLE
Using the dictionary iteration interface to search determine if there
is a key that maps to itself:
.PP
.CS
Tcl_DictSearch search;
Tcl_Obj *key, *value;
int done;

/*
 * Assume interp and objPtr are parameters.  This is the
 * idiomatic way to start an iteration over the dictionary; it
 * sets a lock on the internal representation that ensures that
 * there are no concurrent modification issues when normal
 * reference count management is also used.  The lock is
 * released automatically when the loop is finished, but must
 * be released manually when an exceptional exit from the loop
 * is performed. However it is safe to try to release the lock
 * even if we've finished iterating over the loop.
 */
if (\fBTcl_DictObjFirst\fR(interp, objPtr, &search,
        &key, &value, &done) != TCL_OK) {
    return TCL_ERROR;
}
for (; !done ; \fBTcl_DictObjNext\fR(&search, &key, &value, &done)) {
    /*
     * Note that strcmp() is not a good way of comparing
     * values and is just used here for demonstration
     * purposes.
     */
    if (!strcmp(Tcl_GetString(key), Tcl_GetString(value))) {
        break;
    }
}
\fBTcl_DictObjDone\fR(&search);
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(!done));
return TCL_OK;
.CE
.SH "SEE ALSO"
Tcl_NewObj, Tcl_DecrRefCount, Tcl_IncrRefCount, Tcl_InitObjHashTable
.SH KEYWORDS
dict, dict value, dictionary, dictionary value, hash table, iteration, value
